package main

import (
	"GoStart/opentelemetry/ch03/server/model"
	"github.com/gin-gonic/gin"
	"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	"go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
	otelTrace "go.opentelemetry.io/otel/trace"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"gorm.io/plugin/opentelemetry/tracing"
	"log"
	"os"
	"time"
)

var tp *trace.TracerProvider

const (
	traceName = "mxshop-otel"
)

func tracerProvider() error {
	url := "http://127.0.0.1:14268/api/traces" //这个是jeager对应的地址
	exporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
	if err != nil {
		panic(err)
	}

	tp = trace.NewTracerProvider(
		trace.WithBatcher(exporter),
		trace.WithBatcher(exporter),
		trace.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			//设置trace的名称，不设置默认显示文件名
			semconv.ServiceNameKey.String("mxshop-func"),
		)),
	)
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	return nil
}

func Server(context *gin.Context) {

	ctx := context.Request.Context()
	p := otel.GetTextMapPropagator()
	tracer := tp.Tracer(traceName)
	extract := p.Extract(ctx, propagation.HeaderCarrier(context.Request.Header))
	_, span := tracer.Start(extract, "server")
	time.Sleep(1 * time.Second)
	span.End()
	context.JSON(200, gin.H{})

}

func Server1(c *gin.Context) {

	////负责span的抽取和生成
	//us, _ := c.Value("trace").(string)
	//if us == "" {
	//	panic(us)
	//}
	ctx := c.Request.Context()
	//p := otel.GetTextMapPropagator()
	tr := tp.Tracer(traceName)
	//sctx := p.Extract(ctx, propagation.HeaderCarrier(c.Request.Header))
	traceID := c.Request.Header.Get("trace-id")
	spanID := c.Request.Header.Get("span-id")

	tracid, _ := otelTrace.TraceIDFromHex(traceID)
	spanid, _ := otelTrace.SpanIDFromHex(spanID)
	//tr := otel.Tracer(traceName)
	spanCtx := otelTrace.NewSpanContext(otelTrace.SpanContextConfig{
		TraceID:    tracid,
		SpanID:     spanid,
		TraceFlags: otelTrace.FlagsSampled, //这个如果不设置的话，是不会保存的
		Remote:     true,
	})

	carrier := propagation.HeaderCarrier{}
	carrier.Set("trace-id", traceID)
	propagator := otel.GetTextMapPropagator()
	pctx := propagator.Extract(ctx, carrier)

	sct := otelTrace.ContextWithRemoteSpanContext(pctx, spanCtx)

	_, span := tr.Start(sct, "server")
	time.Sleep(600 * time.Millisecond)
	span.End()
	c.JSON(200, gin.H{})
}

func ServerDB(ctx *gin.Context) {

	dns := "root:123456@tcp(127.0.0.1:3306)/mxshop_good_srv?charset=utf8mb4&parseTime=True&loc=Local"

	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			Colorful: true,
			LogLevel: logger.Info,
		},
	)
	db, err := gorm.Open(mysql.Open(dns), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true,
		},
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	if err := db.Use(tracing.NewPlugin()); err != nil {
		panic(err)
	}

	context := ctx.Request.Context()
	propagator := otel.GetTextMapPropagator()
	tracer := tp.Tracer(traceName)
	extract := propagator.Extract(context, propagation.HeaderCarrier(ctx.Request.Header))
	_, span := tracer.Start(extract, "serverDB")

	if err := db.WithContext(ctx.Request.Context()).Model(model.Brands{}).Where("id = ?", 1).Find(&model.Brands{}); err != nil {
		panic(err)
	}

	time.Sleep(time.Second)
	span.End()
	ctx.JSON(200, gin.H{})

}

func main() {
	_ = tracerProvider()
	r := gin.Default()
	//整合open-telemery直接使用中间件就可以
	r.Use(otelgin.Middleware("my-server"))
	r.GET("/", func(context *gin.Context) {

	})
	r.GET("/server", Server)
	r.GET("/server1", Server1)
	r.GET("/serverdb", ServerDB)
	r.Run(":8090")
}
